import React, { MouseEvent, ReactChildren, ReactChild, ReactNode, useState, useRef, useEffect, useImperativeHandle, Ref, FormEvent, ChangeEvent, SyntheticEvent } from 'react';


export declare interface AppProps{
  onClick: (event: MouseEvent<HTMLButtonElement>) => void;
  // 不好单一的元素不接收数组
  children1: JSX.Element;
  // 不接收字符串
  children2: JSX.Element | JSX.Element[];
  // ReactChildren不是类型 使用程序
  children3: ReactChildren;
  // 接受子数组
  children4: ReactChild[];
  // 推荐
  children: ReactNode;
  functionChildren: (name: string) => ReactNode;
  // css in js
  style?: React.CSSProperties;
  // react 表单事件
  onChange: React.FormEventHandler<HTMLInputElement>;
  // 传递props 明确不转发ref
  props: React.ComponentPropsWithoutRef<"botton">;
}




interface IUser{}
const App = () => {
  // const [user, setUser] = useState<IUser | null>(null);
  const [user, setUser] = useState<IUser>({} as IUser);

  const divRef = useRef<HTMLDivElement>(null);
  const intervalRef = useRef<number | null>(null);

  useEffect(() => {
    if(!divRef.current) {
      throw new Error('对象不可用');
    }

    intervalRef.current = setInterval(() => {}, 300);

    return () => {
      clearInterval(intervalRef.current);
    }

    console.log(divRef.current);
  }, [])

  return <div ref={divRef}>1212</div>
}


type ListProps<ItemProp> = {
  items: ItemProp[],
  innerRef?: Ref<{yideng(item: ItemProp): void}>
}
function App2<ItemProp>(props: ListProps<ItemProp>){
  useImperativeHandle(props.innerRef, () => ({
    yideng(){}
  }))
  return null;
}

type GeetProps = { age: number } & typeof defaultProps;
const defaultProps = {
  age: 21
}
const App3 = ({ age }: GeetProps) => {
  console.log(age);
};

interface IProps {
  name: string;
}
const App4 = ({ name, age }: IProps & typeof defaultProps) => {
  // return [
  //    <div>{name}</div>,
  //    <div>{age}</div>
  // ]

  return <div>{`${name}, ${age}`}</div>
};
App4.defaultProps = defaultProps;

// 怎么去拿别的组件的props
const TestCom = (props: React.ComponentProps<typeof App4>) => {
  return <h1>{props.age}</h1>
}
// 问题很大，必须传入所有属性如name和age，少一个都会报错？？？
const el = <TestCom name='asd' age={123} />


const App5 = () => {

  // FormEvent事件太大
  // FormEvent
  // ChangeEvent
  // SyntheticEvent 合成事件
  const onChange = (e: SyntheticEvent<HTMLInputElement>) => {
    // 如果target读取不到值(极端情况一般不要这么写)
    const target = e.target as typeof e.target;
    // 然后能用target做好多事
  }

  return (
    <div>
      <input type="text" onChange={onChange} />
    </div>
  )
}